#include "myutils.h"

#include <cmath>
#include <float.h>

#include <QApplication>
#include <QScreen>
#include <QProcess>
#include <QDebug>
#include <QTextStream>

/*经度转换*/
double MyUtils::translate_lon(double lon, double lat)
{
    double ret = 300.0 + lon + 2.0*lat + 0.1*lon*lon + 0.1*lon*lat + 0.1*sqrt(abs(lon));
    ret += (20.0 * sin(6.0*lon*PI) + 20.0*sin(2.0*lon*PI)) *2.0 / 3.0;
    ret += (20.0 * sin(lon*PI) + 40.0*sin(lon / 3.0 *PI)) *2.0 / 3.0;
    ret += (150 * sin(lon / 12.0 *PI) + 300.0*sin(lon / 30.0 * PI)) *2.0 / 3.0;

    return ret;
}

/*纬度转换*/
double MyUtils::translate_lat(double lon, double lat)
{
    double ret = -100 + 2.0*lon + 3.0*lat + 0.2*lat*lat + 0.1*lon*lat + 0.2*sqrt((abs(lon)));
    ret += (20.0 *sin(6.0*lon*PI) + 20 * sin(2.0*lon*PI)) *2.0 / 3.0;
    ret += (20.0 *sin(lat*PI) + 40.0*sin(lat / 3.0*PI)) *2.0 / 3.0;
    ret += (160.0*sin(lat / 12.0*PI) + 320.0*sin(lat / 30.0 *PI)) *2.0 / 3.0;

    return ret;
}

/*84转高德*/
POSITION MyUtils::wgs84togcj02(double wgs_lon, double wgs_lat)
{
    POSITION gcj_pos;

    double dlat = translate_lat(wgs_lon - 105.0, wgs_lat - 35.0);
    double dlon = translate_lon(wgs_lon - 105.0, wgs_lat - 35.0);

    double radlat = wgs_lat / 180.0 * PI;

    double magic = sin(radlat);
    magic = 1 - ee * magic*magic;

    double squrtmagic = sqrt(magic);

    dlon = (dlon *180.0) / (a / squrtmagic * cos(radlat)*PI);
    dlat = (dlat *180.0) / ((a*(1 - ee)) / (magic * squrtmagic)*PI);

    gcj_pos.longitude = wgs_lon + dlon;
    gcj_pos.latitude = wgs_lat + dlat;

    return gcj_pos;
}

/*度分格式转度*/
double MyUtils::convertToDegree(double degreeMinute)
{
    // 获取度的整数部分
    int degree = (int)degreeMinute / 100;

    // 获取分的小数部分
    double minute = degreeMinute - degree * 100;

    // 将度分格式转换为度格式
    double degreeFormat = degree + (minute / 60.0);

    return degreeFormat;
}

/*文件是否存在*/
bool MyUtils::fileExists(const QString &filePath)
{
    QFile file(filePath);

    return file.exists();
}

bool MyUtils::createFile(const QString &filePath)
{
    QFile file(filePath);

    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream stream(&file);

        stream << "This is a new file." << endl;

        file.close();

        qDebug() << filePath << "created successfully.";
    } else {
        qCritical() << filePath << "created failed.";

        return false;
    }

    return true;
}

/*路径是否存在*/
bool MyUtils::dirExists(const QString &dirPath)
{
    QDir dir(dirPath);

    return dir.exists();
}

/* 创建目录 */
bool MyUtils::mkMultiDir(const QString &dirPath)
{
    QDir dir;
    QString left_path = "";
    QStringList path_list = dirPath.split('/');

    for (int i = 0; i < path_list.size(); i++)
    {
        left_path.append(path_list[i] + "/");
        if (dirExists(left_path)) {
            continue;
        }
        dir.mkdir(left_path);

        qDebug() << "[UTIL] Path" << left_path;
    }

    return true;
}

/* CRC校验 */
uint16_t MyUtils::CRC16(const uint8_t *tmp, int num)
{
    uint16_t crc = 0xFFFF;
    int i = 0, j = 0;
    uint8_t tmpcrc = 0;

    for (i = 0; i < num; i++) {
        tmpcrc = (uint8_t)(crc & 0xff);
        tmpcrc ^= tmp[i];
        crc &= 0xff00;
        crc |= (uint16_t)(tmpcrc | 0x0);

        for (j = 0; j < 8; j++) {
            if (0x1 == (crc & 0x1)) {
                crc >>= 1;
                crc &= (0x7FFF);
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }

    return crc;
}

/* 获取屏幕高度 */
int MyUtils::screenWidth()
{
    return QGuiApplication::primaryScreen()->geometry().width();
}

/* 获取屏幕宽度 */
int MyUtils::screenHeight()
{
    return QGuiApplication::primaryScreen()->geometry().height();
}

/* 检查IP地址是否正常连接 */
bool MyUtils::checkNetworkConnection(const QString &ipAddress)
{
    bool isNetworkConnected = false;
    QString command = "ping -c 1 " + ipAddress;

    QProcess process;
    process.start(command);
    process.waitForFinished();

    int exitCode = process.exitCode();

    if (exitCode == 0) {
        isNetworkConnected = true;
//        qDebug() << ipAddress << "Network is Connected";

    }
    else {
        isNetworkConnected = false;
        qDebug()<< ipAddress << "Network is DisConnected";
    }

    return isNetworkConnected;
}

/* 解析上传响应 */
bool MyUtils::parseUploadResponse(const QString qstrResponse, const QString qstrType)
{
    QByteArray byteArray = qstrResponse.toUtf8();

    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &jsonError);

    if (!jsonDoc.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if (jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if (jsonObj.contains("code"))
            {
                QJsonValue jsonValue = jsonObj.value("code");
                if (jsonValue.isString())
                {
                    int code = jsonValue.toString().toInt();
                    switch (code) {
                    case 0:
                        return true;
                    case 40001:
                        qWarning() << "[" << qstrType << "] The required parameter is blank or incorrect.";
                        break;
                    case 40022:
                        qWarning() << "[" << qstrType << "] The token is blank or invalid.";
                        break;
                    default:
                        qWarning() << "[" << qstrType << "] The other wrong.";
                        break;
                    }
                }
            }
            else
            {
                qCritical() << "[" << qstrType << "] Request failed, response:" << qstrResponse;
            }
        }
    }

    return false;
}

bool MyUtils::parseInvalidTokenJSON(const QString qstrResponse, int &p_errCode)
{
    QByteArray byteArray = qstrResponse.toUtf8();

    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &jsonError);

    if (!jsonDoc.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if (jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if (jsonObj.contains("code"))
            {
                QJsonValue jsonValue = jsonObj.value("code");
                if (jsonValue.isString())
                {
                    p_errCode = jsonValue.toString().toInt();

                    return true;
                }
            }
        }
    }

    return false;
}

bool MyUtils::parseCalibrationUpload(const QString qstrResponse, QString &picPath)
{
    QByteArray byteArray = qstrResponse.toUtf8();

    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(byteArray, &jsonError);

    if (!jsonDoc.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if (jsonDoc.isObject())
        {
            QJsonObject jsonObj = jsonDoc.object();
            if (jsonObj.contains("code"))
            {
                QJsonValue jsonValue = jsonObj.value("code");
                if (jsonValue.isString())
                {
                    int code = jsonValue.toString().toInt();
                    if (code == 0) {
                        QJsonObject dataObj = jsonObj.value("data").toObject();
                        if (dataObj.contains("picturePath")) {
                            picPath = dataObj.value("picturePath").toString();

                            return true;
                        }
                    }
                }
            }
            else
            {
                qCritical() << "[CALIB] [UPLOAD] Request Failed, Response" << qstrResponse;
            }
        }
    }

    return false;
}

bool MyUtils::parseCalibrationRes(QString qstrResponse, QString &message, QString &showUrl, QString &taskId)
{
    QString jsonString = qstrResponse;
    if (jsonString.isEmpty()) {
        return false;
    }

    qDebug() << "Get calibration result jsonString:" << jsonString;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
    if (!jsonDoc.isNull() && jsonDoc.isObject()) {
        QJsonObject jsonObj = jsonDoc.object();
        if (jsonObj.contains("code")) {
            QJsonValue value = jsonObj.value("code");
            if (value.isDouble()) {
                int code = value.toInt();
                if (200 == code) {
                    QJsonValue messageValue = jsonObj.value("msg");

                    QString retMsg = messageValue.toString();
                    message = cn("标定布角点识别完成！");

                    QJsonValue showUrlValue = jsonObj.value("show_url");

                    showUrl = showUrlValue.toString();

                    QJsonValue taskIdValue = jsonObj.value("task_id");

                    taskId = taskIdValue.toString();
                } else if (201 == code) {
                    QJsonValue jsonMessage = jsonObj.value("msg");

                    message = jsonMessage.toString();

                    qWarning() << "[Get Calibration] Return message:" << message;
                } else if (202 == code) {
                    QJsonValue jsonMessage = jsonObj.value("msg");

                    message = jsonMessage.toString();

                    QJsonValue jsonShowUrl = jsonObj.value("show_url");

                    showUrl = jsonShowUrl.toString();

                    QJsonValue jsonTaskId = jsonObj.value("task_id");

                    taskId = jsonTaskId.toString();

                    qWarning() << "[Get Calibration] " << message;
                } else if (203 == code) {
                    QJsonValue jsonMessage = jsonObj.value("msg");

                    message = jsonMessage.toString();

                    qWarning() << "[Get Calibration] Return message:" << message;
                } else if (204 == code) {
                    QJsonValue jsonMessage = jsonObj.value("msg");

                    message = jsonMessage.toString();

                    qWarning() << "[Get Calibration] Return message:" << message;
                } else if (205 == code) {
                    QJsonValue jsonMessage = jsonObj.value("msg");

                    message = jsonMessage.toString();

                    qWarning() << "[Get Calibration] Return message:" << message;
                } else {
                    qCritical() << "[Get Calibration] Request failed, response:" << qstrResponse;

                    return false;
                }
            } else {
                qCritical() << "[Get Calibration] Request failed, response:" << qstrResponse;

                return false;
            }
        } else {
            qWarning() << "[Get Calibration] Parse calibration response failed.";
            return false;
        }
    } else {
        qWarning() << "[Get Calibration] Calibration response data format is invalid.";
        return false;
    }

    return true;
}

bool MyUtils::parseConfirmCalibraRet(QString qstrResponse, QString &message, QString &taskId)
{
    QString jsonString = qstrResponse;
    if (jsonString.isEmpty()) {
        return false;
    }

    qDebug() << "Get confirm calibration return jsonString:" << jsonString;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8());
    if (!jsonDoc.isNull() && jsonDoc.isObject()) {
        QJsonObject jsonObj = jsonDoc.object();
        if (jsonObj.contains("code")) {
            QJsonValue value = jsonObj.value("code");
            if (value.isDouble()) {
                int code = value.toInt();
                if ((200 == code) || (201 == code)) {
                    QJsonValue messageValue = jsonObj.value("msg");

                    message = messageValue.toString();

                    QJsonValue taskIdValue = jsonObj.value("task_id");

                    taskId = taskIdValue.toString();
                } else {
                    qCritical() << "[Confirm Calibration] Request failed, response:" << qstrResponse;

                    return false;
                }
            } else {
                qCritical() << "[Confirm Calibration] Request failed, response:" << qstrResponse;

                return false;
            }
        } else {
            qWarning() << "[Confirm Calibration] Parse calibration response failed.";
            return false;
        }
    } else {
        qWarning() << "[Confirm Calibration] Calibration response data format is invalid.";
        return false;
    }

    return true;
}
